﻿/**	\file		lxprofile.cxx
 *	\date		(2014-11-29 15:24:04)/(2015-01-01 00:38:39)
 *-----------------------------------------------------------------------------
 *	\brief
 *	\version	1.0.0.1
 *	\author		Nick Shallery	(nicknide@gmail.com)
 *	\copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/

#include	"./lxprofile.hxx"


lolix::lx_u8* g_paramCount;
lolix::lx_u8 g_bufParamCount[2*(lxpref::_EVENT_FLAG_END-1)];


lxpref::_inst::lxprofile_inst::lxprofile_inst(lolix::loli::signal* sign, lolix::dynamic_allocator* alc)
	: _mem_map(WSTRING::quick_compare(), alc)
	, _dat(sign, alc)
{
}


lxpref::_inst::lxprofile_inst::~lxprofile_inst(void)
{
	_cs->release();
	_tinf->release();
	_td_fac->release();
	_sign->release();
	_alc->release();
}


lolix::LOLIX_RETNV
lxpref::_inst::lxprofile_inst::create_inst(
	this_type** out_ptr
	, lolix::dynamic_allocator* alc
	, lolix::ref_factory* ref_fac
	, lolix::toy::time_info* tinf
	, lolix::loli::cs_factory* cs_fac
	, lolix::loli::signal::factory_type* sign_fac
	, lolix::loli::thread_factory* td_fac)
{
	LOLIX_RETNV rtv;
	lolix::loli::critical_section* cs;
	if ( LOLIX_CHECK_ERROR(rtv = cs_fac->create_inst(&cs LOLIX_CS_MARK_NAME_P(L"lxpref::_inst::lxprofile_inst::_cs"))) )
		return rtv;
	atexit_release(*cs);

	lolix::loli::signal* sign;
	if ( LOLIX_CHECK_ERROR(rtv = sign_fac->create_inst(&sign, false)) )
		return rtv;
	atexit_invoke(*sign, release());

	this_type* ptr;
	if ( LOLIX_CHECK_ERROR(rtv = __Create_inst_set_alc(&ptr, alc, ref_fac, sign, alc)) )
		return rtv;
	(ptr->_cs = cs)->inc_ref();
	(ptr->_td_fac = td_fac)->inc_ref();
	(ptr->_tinf = tinf)->inc_ref();
	(ptr->_sign = sign)->inc_ref();
	*out_ptr = ptr;
	return rtv;
}


void
lxpref::_inst::lxprofile_inst::touch(lolix::lx_u32 eventFlag, size_type param_count, const lolix::lx_wchar** name_arr)
{
	lolix::lx_u64 cur_tick;
	_tinf->cur_tick((lolix::lx_i64*)&cur_tick);
	const lolix::size_type g_eventFlagMask = 2 * (lxpref::_EVENT_FLAG_END - 1) - 1;
	LOLIX_ASSERT(eventFlag < g_eventFlagMask, "event flag param error");
	LOLIX_ASSERT(g_paramCount[eventFlag] == param_count, "param count error");
	event_info* einf = this->_dat.query_node();
	einf->enter_time_tick = cur_tick;
	einf->leave_time_tick = 0;

	einf->section_type = eventFlag;
	einf->param_cnt = param_count;
	for ( size_type i = 0; i != param_count; ++i )
		einf->str_param[i] = name_arr[i];
	_td_fac->local_id(&einf->thread_id);
	this->_dat.push_node(einf);
	_tinf->cur_tick((lolix::lx_i64*)&einf->leave_time_tick);
}


lolix::lx_wchar const*
lxpref::_inst::lxprofile_inst::new_string(const lolix::lx_wchar* src)const
{
	WSTRING wstr_src(src, _alc);
	bind_invoke(*_cs, enter(), leave());
	auto rtv = this->_mem_map.insert(lolix::toy::make_pair(wstr_src, 0));
	++rtv.first->second;
	return rtv.first->first.c_str();
}


void
lxpref::_inst::lxprofile_inst::free_string(const lolix::lx_wchar* name)const
{
	WSTRING wstr_src(name, _alc);
	bind_invoke(*_cs, enter(), leave());
	auto iter = this->_mem_map.find(wstr_src);
	LOLIX_ASSERT(iter != this->_mem_map.end(), "Invalid object name");
	if ( !--iter->second )
		this->_mem_map.erase(iter);
}


lolix::LOLIX_RETNV
lxpref::_inst::lxprofile_inst::peek_node(event_info** evt_info)
{
	auto inf = this->_dat.peek();
	if ( !inf )
	{
		*evt_info = 0;
		return lolix::LOLIX_INFO_LOST_SYNC;
	}
	*evt_info = inf;
	return lolix::LOLIX_RETNV_OK;
}


lolix::LOLIX_RETNV
lxpref::_inst::lxprofile_inst::free_node(event_info* evt_inf)
{
	this->_dat.free(evt_inf);
	return lolix::LOLIX_RETNV_OK;
}


lolix::LOLIX_RETNV
lxpref::_inst::lxprofile_inst::wait_node(lolix::toy::time_span const* tinf)const
{
	return this->_sign->wait(tinf);
}


lolix::LOLIX_RETNV
lxpref::_inst::lxprofile_inst::query_signal(lolix::loli::signal** out_sign)
{
	(*out_sign = this->_sign)->inc_ref();
	return lolix::LOLIX_RETNV_OK;
}


void
__Init_cnt_table(void)
{
	//lolix::lx_u8(*g_paramCount)[2 * (lxpref::_SECTION_TYPE_END - 1)];
	//lolix::lx_u8 g_bufParamCount[2 * (lxpref::_SECTION_TYPE_END - 1)];
	if ( g_paramCount )
		return;
	lolix::lx_u32 key_val[] = {
#define	LX_PREF_DEF__EVENT(name, key, is_have_cnt)	key,
	#include	"_lxpref_event_types.inl"
#undef	LX_PREF_DEF__EVENT
	};
	bool key_have_param[] = {
#define	LX_PREF_DEF__EVENT(name, key, is_have_cnt)	is_have_cnt,
	#include	"_lxpref_event_types.inl"
#undef	LX_PREF_DEF__EVENT
	};

	for ( lolix::size_type i = 0; i != ARRAY_SIZE(g_bufParamCount); ++i )
	{
		lolix::size_type key_cnt = 0;
		for ( lolix::size_type x = 0; x != ARRAY_SIZE(key_val); ++x )
		{
			if ( key_val[x] > i )
				break;
			if ( (key_val[x] & i) && key_have_param[x] )
				++key_cnt;
		}
		g_bufParamCount[i] = key_cnt;
	}

	g_paramCount = g_bufParamCount;
}
